Canigó - Reducció de fitxers amb Spring 2.0
Reducció de fitxers de configuracióLa reducció de fitxers de configuració al framework Canigó s'ha realitzat incorporant dues tecnologies diferenciades que ofereixen la reducció de fitxers a diferents apartats de la configuració del framework. Una tecnologia és la que ofereix Spring 2.0 que permet reduïr els fitxers necessaris per a aconseguir els mateixos efectes que s'aconseguien en les versions < 2.0. Una altra tecnologia és la que ofereix SiteMesh, un framework per gestionar el disseny de les aplicacions web. Tot seguit es concreten les possibilitats i l'ús de la tecnologia spring. Spring 2.0Spring 2.0 té una nova capacitat anomenada "extensible XML configuration" a partir de la qual es dóna suport al desenvolupament d'elements fets a mida. Aquests elements fets a mida ofereixen un nou nivell d'abstracció per generar definicions de beans de Spring. El mecanisme d'extensió de XML també proveeix de noves etiquetes per simplificar les tàsques més habituals. Noves etiquetes per a fer les tasques més habitualsPer a poder utilitzar les noves etiquetes és necessari utilitzar els XML Schema en comptes dels DTD, i importar el namespace desitjat. Tanmateix aquestes etiquetes es poden mesclar amb les definicions tradicionals de beans. Exemple de codi que s'ha d'incloure per a usar el namespace tx <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> Les etiquetes que ofereix Spring 2.0 són: Transaction management ("tx"), AOP ("aop"), Java EE ("jee"), Dynamic languages ("lang") i Utils ("util"). Per a més informació cal consultar la documentació de Spring . Així doncs a tall d'exemple aquí es comparen dues tasques en les seves maneres de fer amb Spring 2.0 i amb Spring < 2.0. Definició del datasource amb spring < 2.0 <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="jdbc/jpetsore" /> </bean> Definició del datasource amb spring 2.0 <jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/> Definició del caràcter transaccional pels beans amb spring < 2.0 <bean class="org.springframework...DefaultAdvisorAutoProxyCreator"/> <bean class="org.springframework...TransactionAttributeSourceAdvisor"> <property name="transactionInterceptor ref="transactionInterceptor"/> </bean> <bean id="transactionInterceptor" class="org.springframework...TransactionInterceptor"> <property name="transactionManager" ref="transactionManager"/> <property name="transactionAttributeSource"> <bean class="org.springframework...AnnotationsTransactionAttributeSource"> </bean> </property> </bean> Definició del caràcter transaccional pels beans amb spring 2.0 <tx:annotation-driven /> Implementació d'una extensió XMLLa implementació de namespaces és relativament fàcil. És un procés compost de tres passos. En l'exemple que s'ha posat, el 2n pas està descomposat en dos passos per simplificar la feina. 1. Definir un schema XML. No ha de complir cap restricció especial. El fitxer schema es pot posar allà on es cregui més convenient, sempre i quan després es configuri correctament la seva localització. Exemple de schema <?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns="http://www.springframework.org/schema/myns" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" targetNamespace="http://www.mycompany.com/schema/myns" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xsd:import namespace="http://www.springframework.org/schema/beans"/> <xsd:element name="dateformat"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> <xsd:attribute name="lenient" type="xsd:boolean"/> <xsd:attribute name="pattern" type="xsd:string" use="required"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> </xsd:schema> 2. Generar una classe que implementi la interfície NamespaceHandler. Aquesta classe ha de generar objectes BeanDefinition amb els elements i atributs del schema definit al punt 1. La interfície NamespaceHandler agafa els elements W3C DOM i en genera metadades BeanDefinition processant-los. Spring ja s'encarrega de fer el parseig del XML. Els mètodes de la implementació de la interfídie NamespaceHandler només han de recòrrer l'abre resultant del parseig. Interfície NamespaceHandler public interface NamespaceHandler { void init(); BeanDefinition parse(Element element, ParserContext parserContext); BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext); } El mètode parse() és el més important, té la funcionalitat d'afegir objectes BeanDefinition al context de treball. <bean id="scopedList" class="java.util.ArrayList" scope="request"> <aop:scoped-proxy/> </bean> L'etiqueta <aop:scoped-proxy> modifica l'element regular <bean> que el conté; proporcionant accés a l'objecte BeanDefinition, aquest el pot modificar. Per implementar la interfície NamespaceHandler el que farem serà crear una classe que extengui de la classe NamespaceHandlerSupport, la qual ens facilita el procés introduïnt el concepte de "delegar" (mitjançant el registre de totes les instàncies de la classe BeanDefinitionParser que ens calguin) i després implementar la classe BeanDefinitionParser necessaria. Exemple de classe que hereda de NamespaceHandlerSupport package net.gencat.ctti.canigo.samples.prototip.spring.xmlExtension; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; public class MyNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser()); } } Exemple d'implementació de BeanDefinitionParser package net.gencat.ctti.canigo.samples.prototip.spring.xmlExtension; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; import java.text.SimpleDateFormat; public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected Class getBeanClass(Element element) { return SimpleDateFormat.class; } protected void doParse(Element element, BeanDefinitionBuilder bean) { // this will never be null since the schema explicitly requires that a value be supplied String pattern = element.getAttribute("pattern"); bean.addConstructorArg(pattern); // this however is an optional property String lenient = element.getAttribute("lenient"); if (StringUtils.hasText(lenient)) { bean.addPropertyValue("lenient", Boolean.valueOf(lenient)); } } } 3. Crear els fitxers de configuració spring.handlers per a afegir la implementació de la interfície NamespaceHandler a l'estructura de spring; i spring.schemas per a afegir els schemes a l'estructura de spring. Exemple de fitxer spring.handlers amb els namespaces estàndars http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler http\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler Els arxius de configuració de namespaces s'han d'instal?lar a la carpeta META-INF (en l'exemple s'ha instal?lat a una carpeta "resources/META-INF"). Spring ja s'encarrega de fusionar-los. Exemple de fitxer spring.handlers http\://www.mycompany.com/schema/myns=net.gencat.ctti.canigo.samples.prototip.spring.xmlExtension.MyNamespaceHandler
Exemple de fitxer spring.schemas http\://www.mycompany.com/schema/myns/myns.xsd=spring/xmlExtension/myns.xsd
Per utilitzar aquestes definicions es fa de la mateixa manera que amb els namespaces predefinits de spring: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:myns="http://www.mycompany.com/schema/myns" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.mycompany.com/schema/myns http://www.mycompany.com/schema/myns/myns.xsd"> <!-- as a top-level bean --> <myns:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm" lenient="true"/> </beans> Finalment esmentar que per simplificar la generació de metadades BeanDefinition, Spring 2.0 introdueix una nova classe anomenada BeanDefinitionBuilder que ofereix un constructor amb una API que usa el patró creador. Per a exemples concrets i més informació consulteu la documentació de spring i i concretament l'apèndix B |